--------------------------------------------------------------------------------
--  *  Prog name constant_bandwidth_servers.adb
--  *  Project name CBS
--  *
--  *  Version 1.0
--  *  Last update 09/09/01
--  *
--  *  Created by Antonio Barros on 09/09/01.
--  *  Copyright (c) 2009 CISTER.
--  *  GNAT modified GNU General Public License
--  *


with Ada.Task_Identification; use Ada.Task_Identification;
with Ada.Dispatching.EDF;
--with Ada.Asynchronous_Task_Control;  -- NOT SUPPORTED!!!

-- For debugging purposes only...
with Ada.Text_IO;

package body Constant_Bandwidth_Servers is

  protected body Constant_Bandwidth_Server is

    -- REGISTER ----------------------------------------------------------------
    procedure Register is
    begin
      if First then
        Ada.Text_IO.Put_Line("First register...");
        First := false;
        Server_Budget.Add(Milliseconds(Period));
        Server_Budget.Set_Handler(Budget_Exausted'Access);
      end if;

      -- Just insert the current task in the Group_Budget.
      Server_Budget.Add_Task(Current_Task);
    end Register;

    -- RELEASE -----------------------------------------------------------------
    procedure Release is
      Release_Time : Time := Clock;
      --Us : Time_Span := Qs / Ts;
      Budget_Required : Time_Span;
    begin
      -- Check if server is idle.
      if Idle then

        -- No longer idle.
        Idle := false;
        Ada.Text_IO.Put_Line("1");
        -- TO DO: 'Budget' and 'Period' are Integer representations of Time_Span
        --        values, in MILLISECONDS. This is not the proper way to
        --        represent these values.
        -- Ada.Real_Time only allows multiplications and divisions of Time_Span
        -- with Integer.
        Budget_Required := Budget * (Deadline - Release_Time) / Period;

        Ada.Text_IO.Put_Line("2");
        if Server_Budget.Budget_Remaining >= Budget_Required then
          -- Compute next server deadline.
          Ada.Text_IO.Put_Line("3.1");
          Deadline := Release_Time + Ts;
          -- Assign current server deadline
          -- to served task.
          Ada.Text_IO.Put_Line("3.2");
          Ada.Dispatching.EDF.Set_Deadline(Deadline);
          -- Record current executing job.
          Ada.Text_IO.Put_Line("3.3");
          Current_Job := Current_Task;
          Ada.Text_IO.Put_Line("3.4");
        end if;

      else
        -- Enqueue the request in a queue of pending jobs.
        -- TO DO!!!!!
        Pending_Jobs := Pending_Jobs + 1;
        --Asynchronous_Task_Control.Hold(Current_Task);
      end if;
    end Release;

    -- FINISH ------------------------------------------------------------------
    procedure Finish is
    begin
      if Current_Job /= Current_Task then
        null;
      end if;

      if Pending_Jobs > 0 then
        -- Fetch first pending job.
        -- TO DO!!!
        -- Current_Job := ...

        Pending_Jobs := Pending_Jobs - 1;

        -- Assign current deadline to job.
        Ada.Dispatching.EDF.Set_Deadline(Deadline, Current_Job);

        -- Continue current job.
        -- Asynchronous_Task_Control.Continue(Current_Job);

      else
        Idle := true;
      end if;
    end Finish;

    -- BUDGET EXAUSTED ---------------------------------------------------------
    procedure Budget_Exausted(G : in out Group_Budget) is
    begin
      Ada.Text_IO.Put_Line("REPLENISHING!!!");
      -- Calculate a new deadline and assign it to the served task
      Deadline := Deadline + Ts;
      -- Replenish budget to maximum value.
      G.Replenish(Qs);
      -- Assign new deadline to active job.
      Ada.Dispatching.EDF.Set_Deadline(Deadline, Current_Job);
    end Budget_Exausted;

  end Constant_Bandwidth_Server;

end Constant_Bandwidth_Servers;
